package com.zhiche.lisa.bms.service.utils.common.identityCodeUtil.impl;

import com.baomidou.mybatisplus.service.IService;
import com.zhiche.lisa.bms.service.utils.common.identityCodeUtil.CodeSuper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author: liuanshun
 * @Description:
 * @Date: Create in 13:39 2018/11/16
 */
public abstract class ServiceCode<SeriveT extends IService> extends CodeSuper {
    //自增数值标识
    private final String INCREMENT_NEXT_MAPPER_NAME = "[incrementId]";
    //外部替换标识
    private final char[] O_REPLACE_C = new char[]{'{', '}'};
    //内部自替换标识
    private final char[] I_REPLACE_C = new char[]{'[', ']'};
    //重置\格式化，组标识
    private final char[] CHECK_REPLACE_C = new char[]{'^', '%'};
    //所属同组的字符
    protected final String CHECK_STR;


    /**
     * 对应初始化数据时操作获取数据的Service
     */
    protected SeriveT importService;

    /**
     * 格式化映射数据
     */
    protected abstract void factoryDateMapping();

    /**
     * 自主检测映射数据
     *
     * @return
     */
    protected abstract boolean checkDateMapping();

    /**
     * 获取之前跌增的id（由数据库寻找）
     *
     * @return 存在结果的String类型id结果，或者是不存在结果的null
     */
    protected abstract Integer getAfterInitId();

    /**
     * 初始化构造
     *
     * @param importService
     */
    public ServiceCode(SeriveT importService) {
        //导入Service
        this.importService = importService;
        //初始化数据
        this.mapper = new HashMap<>();
        this.codeFactory = "";
        this.factoryDateMapping();
        CHECK_STR = this.bindCheckChar();
    }

    /**
     * 初始化构造
     *
     * @param importService
     * @param codeFactory
     */
    protected ServiceCode(SeriveT importService, String codeFactory) {
        //导入Service
        this.importService = importService;
        //初始化数据
        this.mapper = new HashMap<>();
        this.codeFactory = codeFactory;
        this.factoryDateMapping();
        CHECK_STR = this.bindCheckChar();
    }

    /**
     * 获取检查字符
     *
     * @return
     */
    private String bindCheckChar() {
        int checkStartIndex = codeFactory.indexOf(CHECK_REPLACE_C[0]);
        int checkEndIndex = codeFactory.lastIndexOf(CHECK_REPLACE_C[1]);
        if (checkStartIndex >= 0 && checkStartIndex < checkEndIndex) {
            String substring = codeFactory.substring(checkStartIndex + 1, checkEndIndex);
            //removeEndChr
            codeFactory = codeFactory.substring(0, checkEndIndex) + codeFactory.substring(checkEndIndex + 1, codeFactory.length());
            //removeStartChr
            codeFactory = codeFactory.substring(0, checkStartIndex) + codeFactory.substring(checkStartIndex + 1, codeFactory.length());
            return substring;
        }
        return null;
    }

    /**
     * 初始化id自增号
     *
     * @return
     */
    @Override
    public ServiceCode init() {
        Integer afterInitId = this.getAfterInitId();
        if (afterInitId == null) {
            codeId = new AtomicInteger(0);
        } else {
            codeId = new AtomicInteger(afterInitId);
        }
        return this;
    }

    /**
     * 获取下一个自增id
     *
     * @return
     */
    @Override
    protected String getNextIncrementId() {
        int newNum = codeId.incrementAndGet();
        //数字长度为4位，长度不够数字前面补0
        String newStrNum = String.format("%04d", newNum);
        return newStrNum;
    }

    /**
     * 获取下一个code
     *
     * @param valueMapping 动态映射字符（传入以格式定义关键字为key的映射值）
     * @return 转换后的code结果
     */
    protected String getNextCode(String codeFactory, Map<String, String> valueMapping) {
        //判断固定生成的时间映射，是否为当前日期
        if (this.checkDateMapping()) {
            /*
             * 相同，映射结果正常
             */
            String replaceStr = codeFactory;
            //遍历同步内部固定资源，并替换结果值
            for (Map.Entry<String, String> item :
                    mapper.entrySet()) {
                replaceStr = StringUtils.replace(replaceStr, I_REPLACE_C[0] + (item.getKey() == null ? "" : item.getKey()) + I_REPLACE_C[1], (item.getValue() == null ? "" : item.getValue()));
            }
            if (!CollectionUtils.isEmpty(valueMapping)) {
                //遍历非内部固定值的动态资源，并替换结果值
                for (Map.Entry<String, String> item :
                        valueMapping.entrySet()) {
                    //按默认方式替换
                    replaceStr = StringUtils.replace(replaceStr, O_REPLACE_C[0] + (item.getKey() == null ? "" : item.getKey()) + O_REPLACE_C[1], (item.getValue() == null ? "" : item.getValue()));
                }
            }
            //替换生成的id号（自增标识验证，若不存在不自增id）
            if (replaceStr.contains(INCREMENT_NEXT_MAPPER_NAME)) {
                String nextId = this.getNextIncrementId();
                replaceStr = StringUtils.replace(replaceStr, INCREMENT_NEXT_MAPPER_NAME, (nextId == null ? "" : nextId));
            }
            return replaceStr;
        } else {
            /*
             * 不相同，更新映射值，并初始化剩余资源，
             */
            this.factoryDateMapping();
            this.init();
            //继续调用自身，重新转换
            return this.getNextCode(valueMapping);
        }
    }
}
